package com.example.mydemo.utils

import android.graphics.SurfaceTexture
import android.opengl.GLUtils
import android.util.Log
import javax.microedition.khronos.egl.EGL10
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.egl.EGLContext

object EGLConfigManager {

    private const val EGL_CONTEXT_CLIENT_VERSION = 0x3098
    private const val EGL_OPENGL_ES2_BIT = 4

    private var mEgl: EGL10? = null
    private var mEglDisplay = EGL10.EGL_NO_DISPLAY          // 显示设备
    private var mEglSurface = EGL10.EGL_NO_SURFACE
    private var mEglContext = EGL10.EGL_NO_CONTEXT

    /**
     * 创建绘制egl窗口
     */
    fun createEglContext(surface: SurfaceTexture?): Boolean {
        try {
            mEgl = (EGLContext.getEGL() as EGL10?)?.apply {
                mEglDisplay = this.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY) // 获取显示设备

                if (mEglDisplay === EGL10.EGL_NO_DISPLAY) onFail("eglGetDisplay failed : ", this)

                //version中存放EGL 版本号，int[0]为主版本号，int[1]为子版本号
                val version = IntArray(2)
                if (!this.eglInitialize(mEglDisplay, version)) onFail("eglInitialize failed : ", this)

                // 构造需要的特性列表
                val configurations = intArrayOf(
                    // EGL10.EGL_BUFFER_SIZE, 32,
                    EGL10.EGL_ALPHA_SIZE, 8,    // 指定Alpha大小，以下四项实际上指定了像素格式
                    EGL10.EGL_BLUE_SIZE, 8,     // 指定B大小
                    EGL10.EGL_GREEN_SIZE, 8,    // 指定G大小
                    EGL10.EGL_RED_SIZE, 8,      // 指定RGB中的R大小（bits）
                    EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,  // 指定渲染api类别,这里或者是硬编码的4，或者是EGL14.EGL_OPENGL_ES2_BIT
                    EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT, EGL10.EGL_NONE  // 总是以EGL10.EGL_NONE结尾
                )

                val numConfigs = IntArray(1)
                val configs = arrayOfNulls<EGLConfig>(1)
                // eglChooseConfig(display, attributes, configs, num, configNum);
                // 用于获取满足attributes的所有config，参数1、2其意明显，参数3用于存放输出的configs，参数4指定最多输出多少个config，参数5由EGL系统写入，表明满足attributes的config一共有多少个
                // 获取所有满足attributes的configs,并选择一个
                if (!this.eglChooseConfig(mEglDisplay, configurations, configs, 1, numConfigs)) onFail("eglChooseConfig failed : ", this)

                // attrib_list,目前可用属性只有EGL_CONTEXT_CLIENT_VERSION, 1代表OpenGL ES 1.x,
                val contextAttr = intArrayOf(EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE)
                // 2代表2.0。同样在Android4.2之前，没有EGL_CONTEXT_CLIENT_VERSION这个属性，只能使用硬编码0x3098代替
                // share_context,是否有context共享，共享的context之间亦共享所有数据。EGL_NO_CONTEXT代表不共享
                // 创建context
                mEglContext = this.eglCreateContext(mEglDisplay, configs[0], EGL10.EGL_NO_CONTEXT, contextAttr)

                // 负责对Android Surface的管理
                // 获取显存，create a new EGL window surface
                mEglSurface = this.eglCreateWindowSurface(mEglDisplay, configs[0], surface, null)

                if (mEglSurface === EGL10.EGL_NO_SURFACE || mEglContext === EGL10.EGL_NO_CONTEXT) {
                    if (this.eglGetError() == EGL10.EGL_BAD_NATIVE_WINDOW) onFail("eglCreateWindowSurface returned  EGL_BAD_NATIVE_WINDOW. ", this)
                    else onFail("eglCreateWindowSurface failed : ", this)
                }

                // 设置为当前的渲染环境
                if (!this.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) onFail("eglMakeCurrent failed : ", this)
            }
            return true
        } catch (e: Exception) {
            e.printStackTrace()
        }

        return false
    }

    /**
     * 创建失败
     */
    private fun onFail(msg: String, mEgl: EGL10) {
        throw RuntimeException("$msg ${GLUtils.getEGLErrorString(mEgl.eglGetError())}")
    }

    /**
     * 关闭egl
     */
    fun destroyLEGLESSContext() {
        try {
            val destroyContext = mEgl?.eglDestroyContext(mEglDisplay, mEglContext)
            val eglDestroySurface = mEgl?.eglDestroySurface(mEglDisplay, mEglSurface)
            Log.d("DrawGiftEglCore", "destroyContext : $destroyContext  eglDestroySurface : $eglDestroySurface")
            mEglContext = EGL10.EGL_NO_CONTEXT
            mEglSurface = EGL10.EGL_NO_SURFACE
            mEglDisplay = EGL10.EGL_NO_DISPLAY
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 更新帧
     */
    fun swapBuffer() {
        mEgl?.eglSwapBuffers(mEglDisplay, mEglSurface)
    }

}